package com.mingke.java.AIO;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

/**
 * 一个检测Socket连接的面向流的异步通道
 *
 * 当前执行本类中的open类方法的时候，一个异步的SocketServer就会被创建。
 * 一个新创建的异步SocketServer被打开后，是还没有绑定服务端口的。可以通过bind方法使得当前通道绑定到一个固定的服务端口。
 * 一旦完成绑定，accept方法就能够用以接受一个客户端的连接，并得到对应的通道。
 * 相应的，如果试图在一个未绑定服务端口执行accept方法则会抛出一个异常--NotYetBoundException
 *
 * 当前的SocketServer通道在多个客户端线程连接时是安全的，尽管在任何时候都至多会有一个线程在等待
 * 如果一个线程在先前的线程执行连接完成的回调之前发起了accept那么会抛出一个异常--AcceptPendingException
 *
 * 同样的的可以通过setOption方法设置相关的参数，当前的通道支持设置以下参数
 * SO_RCVBUF: 通道接收缓冲区的大小
 * SO_REUSEADDR: 复用的服务地址
 * 当然，其他的特殊参数也是支持的
 * 一个简明的使用例程
 *  final AsynchronousServerSocketChannel listener =
 *         AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));
 *
 *     listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
 *         public void completed(AsynchronousSocketChannel ch, Void att) {
 *             // accept the next connection
 *             listener.accept(null, this);
 *
 *             // handle this connection
 *             handle(ch);
 *         }
 *         public void failed(Throwable exc, Void att) {
 *             ...
 *         }
 *     });
 */
/**
 * @author mingke
 * @function AIO的实例，利用AIO的回调机制，实现的一个异步非阻塞的IO模型
 * @date 2021/11/9
 */
public class AIOSocketServer {
    //启动服务端的代码
    public void AIOServerRun() {
        //设置服务器的端口号
        InetSocketAddress inetSocketAddress = new InetSocketAddress(2021);
        try {
            final AsynchronousServerSocketChannel channel = AsynchronousServerSocketChannel.open();
            channel.bind(inetSocketAddress);
            System.out.println("服务器启动完毕");
            channel.accept(channel, new AIOAcceptHandler());
        }catch(Exception e) {
            e.printStackTrace();
        }
        //弄一个线程过来的目的是不让当前这个服务端直接结束
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.start();
    }

}
